home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Latest Windows '95 Programs
/
The Latest Windows 95 Programs.iso
/
win95
/
internet
/
finger
/
netwrkm.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-11-10
|
9KB
|
294 lines
//
// Finger Version 3.1, a Windows Sockets Finger Client
//
// Copyright 1992, 1993 Network Research Corporation
//
// Permission to use, modify, and distribute this software and its
// documentation for any purpose and without fee is hereby granted, provided
// that the above copyright notice appears in all copies and that both
// that copyright notice and this permission notice appear in supporting
// documentation. NRC makes no claims as to the suitability of this software
// for any purpose.
//
// Module NETWRKM uses Windows Sockets asynchronous (message based) calls to
// query a remote finger server for a list of currently logged in users.
// Module FINGER initiates the operation by calling FingerStart(), and
// NETWRKM signals completion by calling FingerFinish(). NETWRKM uses DSPLIST
// functions to send the retrieved data to the FINGER user interface module.
//
// 04/01/92 Lee Murach Created.
// 11/30/92 Lee Murach Adapted for WS 1.1 WSAAsyncSelect()
// 12/02/92 Lee Murach Restructured for Finger 3.0 integrated release
// 01/15/92 Lee Murach Change FD_READ to FD_READ | FD_CLOSE
// 03/01/93 Lee Murach Added WSAEWOULDBLOCK check to DoConnect()
// 03/25/93 Lee Murach Added per-user finger support.
//
#include <memory.h>
#include <string.h>
#include <windows.h>
#include <winsock.h>
#include "finger.h"
// messages for windows sockets returns
#define WM_SERVICE (WM_USER + 1)
#define WM_HOSTRESOLVED (WM_USER + 2)
#define WM_CONNECTED (WM_USER + 3)
#define WM_OKTORECV (WM_USER + 4)
#define NETWINDOW "NetWindow"
LONG FAR APIENTRY NetWndProc(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam);
LONG DoResolveHost(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam);
LONG DoConnect(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam);
LONG DoQuery(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam);
LONG DoRetrieval(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam);
void LoadEntBuf(IPA ipa);
DECODEWORD netMsgs[] = // network window messages & handlers
{
WM_SERVICE, DoResolveHost,
WM_HOSTRESOLVED, DoConnect,
WM_CONNECTED, DoQuery,
WM_OKTORECV, DoRetrieval
};
SOCKET Sock; // connects to remote server's socket
int Port; // hold port for finger service
char EntBuf[MAXGETHOSTSTRUCT]; // buf for service & resolve returns
HWND hNetWnd; // network window handle
//
// InitNetApp -- registers window class for the network module's invisible
// child window. This is called only for the first instance of finger.
//
VOID InitNetApp(VOID)
{
WNDCLASS wndclass;
wndclass.style = 0;
wndclass.lpfnWndProc = NetWndProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = hInst;
wndclass.hIcon = 0;
wndclass.hCursor = 0;
wndclass.hbrBackground = 0;
wndclass.lpszMenuName = NULL;
wndclass.lpszClassName = NETWINDOW;
RegisterClass(&wndclass);
}
//
// InitNetInst -- initializes the network module by creating an invisible
// child of the main finger window which will be used to receive Windows
// Sockets notification messages. The window will be automatically
// destroyed when the main window exits, so no finalization is required.
//
VOID InitNetInst(HWND hWnd)
{
hNetWnd = CreateWindow( NETWINDOW, "", WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
hWnd, 0, hInst, NULL);
}
//
// NetWndProc -- callback function for network window. The network window
// is a child window created especially to receive windows sockets network
// messages. The function decodes and routes to appropriate message handler.
//
LONG FAR APIENTRY NetWndProc(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
{
int i;
for (i = 0; i < dim(netMsgs); i++)
{
if (wMsg == netMsgs[i].Code)
return((*netMsgs[i].Fxn)(hWnd, wMsg, wParam, lParam));
}
return(DefWindowProc(hWnd, wMsg, wParam, lParam));
}
//
// FingerStart -- called by FINGER module to initiate a conversation with
// the remote finger server. We start by resolving the finger tcp service
// to a port number. Windows Sockets WSAAsync routines signal completion
// by posting messages, which are dispatched to appropriate handlers.
//
VOID FingerStart(VOID)
{
if (WSAAsyncGetServByName(hNetWnd, WM_SERVICE, "finger", "tcp",
EntBuf, sizeof(EntBuf)) == -1)
{
ReportFingerErr(FE_NOPORT);
FingerFinish(FE_ERROR);
}
}
//
// DoResolveHost -- resolves host specifier to an IP address. Since we
// allow a "dotted decimal" IP address to be entered in lieu of a DNS host
// name, we check for this syntax before assuming a DNS name.
//
LONG DoResolveHost(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
{
IPA ipa;
if (WSAGETSELECTERROR(lParam))
{
ReportFingerErr(FE_NOPORT); // cannot locate finger service
FingerFinish(FE_ERROR);
return(FALSE);
}
Port = ((SERVENT *)EntBuf)->s_port; // we're going to reuse the buffer
// if host specifier is dotted decimal ip address, resolve right here
if ((ipa = INET_ADDR(szHostName)) != INADDR_NONE)
{
LoadEntBuf(ipa);
PostMessage(hNetWnd, WM_HOSTRESOLVED, 0, 0);
return(FALSE);
}
// assume specifier is DNS host name
if (WSAAsyncGetHostByName(hNetWnd, WM_HOSTRESOLVED, szHostName,
EntBuf, sizeof(EntBuf)) == -1)
{
ReportFingerErr(FE_NOHOST);
FingerFinish(FE_ERROR);
}
return(FALSE);
}
//
// LoadEntBuf -- loads the EntBuf (sufficiently) with a HOSTENT and
// referenced IPA. This is so we can return IPAs in the same
// manner as a WSAAsync call.
//
void LoadEntBuf(IPA ipa)
{
LPHOSTENT phe = (LPHOSTENT) EntBuf;
LPPIPA ppipa = (LPPIPA) (EntBuf + sizeof(HOSTENT));
LPIPA pipa = (LPIPA) (EntBuf + sizeof(HOSTENT) + sizeof(LPPIPA));
memset(phe, 0, sizeof(HOSTENT));
phe->h_addr_list = (char FAR * FAR *) ppipa;
*ppipa = pipa;
*pipa = ipa;
}
//
// DoConnect -- allocates a socket and connects to remote finger server.
//
LONG DoConnect(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
{
if (WSAGETSELECTERROR(lParam))
{
ReportFingerErr(FE_NOHOST); // could not resolve host name
FingerFinish(FE_ERROR);
return(FALSE);
}
if ((Sock = socket(AF_INET, SOCK_STREAM, 0)) >= 0)
{
SOCKADDR_IN server;
u_long block = FALSE;
HOSTENT *phe = (HOSTENT *) EntBuf;
memset(&server, 0, sizeof(server));
server.sin_family = AF_INET;
server.sin_port = Port;
server.sin_addr = *((IN_ADDR FAR *) *phe->h_addr_list);
// post message when connect is established
WSAAsyncSelect(Sock, hNetWnd, WM_CONNECTED, FD_CONNECT);
if ( connect(Sock, (SOCKADDR *)&server, sizeof(server)) < 0 &&
WSAGetLastError() != WSAEWOULDBLOCK)
{
ReportFingerErr(FE_NOCONN);
FingerFinish(FE_ERROR);
}
}
else
{
ReportFingerErr(FE_NOSOCK);
FingerFinish(FE_ERROR);
}
return(FALSE);
}
//
// DoQuery -- sends a query for all currently logged in users to remote
// server.
//
LONG DoQuery(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
{
char msg[MAXUSER+3];
int msglen;
if (WSAGETSELECTERROR(lParam))
{
ReportFingerErr(FE_NOCONN); // could not connect to server
FingerFinish(FE_ERROR);
return(FALSE);
}
// post message when data is available for read
WSAAsyncSelect(Sock, hNetWnd, WM_OKTORECV, FD_READ | FD_CLOSE);
strcpy(msg, szUser);
strcat(msg, "\r\n");
msglen = strlen(msg);
if (send(Sock, msg, msglen, 0) != msglen)
{
ReportFingerErr(FE_NOSEND);
FingerFinish(FE_ERROR);
return(FALSE);
}
OpenDisplayList(); // new display list will contain received data
return(FALSE);
}
//
// DoRetrieval -- fetches ascii text from remote finger server, and builds
// display list until the end of the text stream.
//
LONG DoRetrieval(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
{
static char buf[500];
int nchars, err = 0;
/* receives data not to exceed buf size & reenables notification
of more data pending */
if ((nchars = recv(Sock, (char FAR *)&buf, sizeof(buf), 0)) > 0)
{
PushChars(buf, nchars); // adds character to display list
return(FALSE);
}
CloseDisplayList(); // close list if error or end-of-data
closesocket(Sock); // don't need socket anymore
if (nchars < 0)
{
FreeDisplayList();
ReportFingerErr(FE_NORECV); // error during receive
err = FE_ERROR;
}
FingerFinish(err); // signal end-of-finger
return(FALSE);
}